package limeirafol;

import java.io.File;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import limeirafol.remote.ParametroVO;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import lbframework.bean.consultaCampo.LBConsultaCampo;
import lbframework.bean.jasperViewer.LBJasperViewerGUI;
import lbframework.classe.Conexao;
import lbframework.classe.Email;
import lbframework.classe.Util;
import lbframework.classe.LBException;
import lbframework.classe.OperacaoCanceladaException;
import lbframework.classe.ProgressBar;
import limeirafol.bean.BeanSistema;
import limeirafol.remote.Formulario;
import limeirafol.remote.TipoOperacao;
import limeirafol.remote.cadastro.ProdutoVO;
import limeirafol.remote.cadastro.TipoProduto;
import limeirafol.remote.sistema.EmailVO;

public class Global {

    public static int IDPROGRAMA = 0;
    public static String VERSAO = "1.0.0";
    public static String DATA = "16/01/2012";
    public static int idLoja = 0;
    public static String loja = "";
    public static int idEstado = 0;
    public static int idUsuario = 0;
    public static String usuario = "LUCAS BATISTA";

    public static void verificarProdutoAssociadoEstoque(LBConsultaCampo i_consultaProduto, String i_title) throws Exception {
        Statement stm = null;
        StringBuilder sql = null;
        ResultSet rst = null;

        stm = Conexao.createStatement();

        sql = new StringBuilder();
        sql.append("SELECT associadoitem.id_produto");
        sql.append(" FROM associado");
        sql.append(" INNER JOIN associadoitem ON associado.id = associadoitem.id_associado");
        sql.append(" WHERE associado.id_produto = " + i_consultaProduto.getId());
        sql.append(" AND associadoitem.aplicaestoque = TRUE");
        sql.append(" AND associado.id_situacaocadastro = 1");

        rst = stm.executeQuery(sql.toString());

        if (rst.next()) {
            try {
                Util.exibirMensagemConfirmar("Confirma lançamento do produto associado?", i_title);

                i_consultaProduto.setId(rst.getInt("id_produto"));
                i_consultaProduto.consultar();

            } catch (Exception ex) {
                i_consultaProduto.clear();
                i_consultaProduto.requestFocus();

                throw new OperacaoCanceladaException();
            }
        }

        rst.close();
    }

    public static void atualizaDataProcessamento(String data) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT * FROM dataprocessamento WHERE id = 1");

        if (rst.next()) {
            sql = new StringBuilder();
            sql.append("UPDATE dataprocessamento SET");
            sql.append(" data = '" + data + "'");
            sql.append(" WHERE id = 1");

            stm.execute(sql.toString());

        } else {
            sql = new StringBuilder();
            sql.append("INSERT INTO dataprocessamento (data) VALUES (");
            sql.append("'" + data + "')");


            stm.execute(sql.toString());
        }

        stm.close();
    }

    public static String consultaDataProcessamento() throws Exception {
        String data = "";
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        stm = Conexao.createStatement();

        sql = new StringBuilder();
        sql.append("SELECT * FROM dataprocessamento WHERE id = 1");
        rst = stm.executeQuery(sql.toString());

        if (rst.next()) {
            data = rst.getString("data");
        }
        stm.close();

        return data;
    }

    public static String calcularSenhaTransferencia(int i_numero, String i_data, int i_idLoja) throws Exception {
        int data = Integer.parseInt(new SimpleDateFormat("ddMMyyyy").format(new SimpleDateFormat("dd/MM/yyyy").parse(i_data)));

        String senha = Util.formatNumber(Long.toHexString((long) i_numero * data * i_idLoja), 8).substring(0, 8);

        return senha.toUpperCase();
    }

    public static void verificarVersao() throws Exception {
        Statement stm = null;
        ResultSet rst = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT versao FROM versao WHERE id_programa = " + Global.IDPROGRAMA);

        if (!rst.next() || !rst.getString("versao").equals(Global.VERSAO)) {
            if (Global.idUsuario == 0) {
                Util.exibirMensagemContinuar("Versão incorreta do sistema!", "Atenção");
            } else {
                throw new LBException("Versão incorreta do sistema!");

            }
        }

        stm.close();
    }

    public static void imprimir(String i_arquivo, Collection i_collection, Map i_parametro) throws Exception {
        imprimir(i_arquivo, i_collection, i_parametro, null, false);
    }

    public static void imprimir(String i_arquivo, Collection i_collection, Map i_parametro, Comparator i_comparator, boolean i_permiteVazio) throws Exception {
        if (new File("rpt/custom/" + i_arquivo).exists()) {
            i_arquivo = "custom/" + i_arquivo;
        }

        if (!i_permiteVazio) {
            if (i_collection == null || i_collection.size() <= 0) {
                throw new LBException("Não existem itens listados para impressão!");
            }
        }

        Collection newCollection = new ArrayList();
        newCollection.addAll(i_collection);

        if (i_comparator != null) {
            Collections.sort((List) newCollection, i_comparator);
        }

        carregarEmail();

        JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(newCollection, true);

        if (i_parametro == null) {
            i_parametro = new HashMap();
        }

//        i_parametro.put("DESCRICAO_LOJA", Global.fornecedor + " - " + Global.loja);

        JasperPrint js = JasperFillManager.fillReport("rpt/" + i_arquivo, i_parametro, ds);

        LBJasperViewerGUI viewer = new LBJasperViewerGUI(js);

        ProgressBar.dispose();

        viewer.setVisible(true);
    }

    public static void carregarEmail() throws Exception {
        BeanSistema beanSistema = new BeanSistema();

        EmailVO oEmail = beanSistema.carregarEmail(Global.idUsuario);

        Email.usuario = oEmail.email;
        Email.senha = oEmail.senha;
        Email.servidor = oEmail.servidor;
        Email.autenticacao = oEmail.requerAutenticacao;
        Email.tls = oEmail.tls;
        Email.porta = oEmail.porta;
    }

    public static ParametroVO getParametro(int i_id) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        stm = Conexao.createStatement();

        sql = new StringBuilder();
        sql.append("SELECT p.id, p.descricao, COALESCE(pv.valor, '') AS valor");
        sql.append(" FROM parametro AS p");
        sql.append(" LEFT JOIN parametrovalor AS pv ON pv.id_parametro = p.id");
        sql.append(" WHERE p.id = " + i_id);

        rst = stm.executeQuery(sql.toString());

        ParametroVO oParametro = new ParametroVO();

        if (rst.next()) {
            oParametro.id = rst.getInt("id");
            oParametro.descricao = rst.getString("descricao");
            oParametro.valor = rst.getString("valor");
        }

        stm.close();

        return oParametro;
    }

    public static void salvarParametro(Vector<ParametroVO> i_parametro) throws Exception {
        try {
            Conexao.begin();

            for (ParametroVO oParametro : i_parametro) {
                salvarParametro(oParametro);
            }

            Conexao.commit();

        } catch (Exception ex) {
            Conexao.rollback();
            throw ex;
        }
    }

    public static void salvarParametro(ParametroVO i_parametro) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        try {
            Conexao.begin();
            stm = Conexao.createStatement();

            rst = stm.executeQuery("SELECT id FROM parametrovalor WHERE id_parametro = " + i_parametro.id);

            if (rst.next()) {
                sql = new StringBuilder();
                sql.append("UPDATE parametrovalor SET");
                sql.append(" valor = '" + i_parametro.valor.replace("\\", "\\\\") + "'");
                sql.append(" WHERE id_parametro = " + i_parametro.id);


                stm.execute(sql.toString());

            } else {
                sql = new StringBuilder();
                sql.append("INSERT INTO parametrovalor (id_parametro, valor) VALUES (");
                sql.append(i_parametro.id + ", ");
                sql.append("'" + i_parametro.valor.replace("\\", "\\\\") + "')");

                stm.execute(sql.toString());
            }

            stm.close();
            Conexao.commit();

        } catch (Exception ex) {
            Conexao.rollback();
            throw ex;
        }
    }

    public static void atualizarCustoAcessorio(long i_id, double i_custo) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        try {
            Conexao.begin();
            stm = Conexao.createStatement();

            //atualiza todos os produtos com o novo custo do acessorio.
            sql = new StringBuilder();
            sql.append("UPDATE produtoitem SET");
            sql.append(" custototal = quantidade * " + i_custo);
            sql.append(" WHERE id_acessorio = " + i_id);
            stm.execute(sql.toString());

            //Pega todos os produtos com aquele acessorio
            sql = new StringBuilder();
            sql.append("SELECT distinct pi.id_produto, p.id_tipoproduto, SUM(pi.custototal) AS custototal");
            sql.append(" FROM produtoitem as pi");
            sql.append(" INNER JOIN produto as p on p.id = pi.id_produto");
            sql.append(" WHERE id_acessorio = " + i_id);
            sql.append(" GROUP BY pi.id_produto, p.id_tipoproduto");
            rst = stm.executeQuery(sql.toString());

            List<ProdutoVO> vItem = new ArrayList();
            while (rst.next()) {
                ProdutoVO oItem = new ProdutoVO();
                oItem.id = rst.getInt("id_produto");
                oItem.idTipoProduto = rst.getInt("id_tipoproduto");
                oItem.custoAcessorio = rst.getDouble("custototal");

                vItem.add(oItem);
            }

            double custoOutros = 0;

            //atualiza custo do produto
            for (ProdutoVO oProduto : vItem) {
                //seleciona custo dos demais acessorios
                sql = new StringBuilder();
                sql.append("SELECT SUM(pi.custototal) AS custototal");
                sql.append(" FROM produtoitem as pi");
                sql.append(" WHERE id_produto = " + oProduto.id + "AND id_acessorio NOT IN (" + i_id + ")");
                rst = stm.executeQuery(sql.toString());

                if (rst.next()) {
                    custoOutros = rst.getDouble("custototal");
                }

                sql = new StringBuilder();
                sql.append(" UPDATE produto SET");

                if (oProduto.idTipoProduto == TipoProduto.BRINCO.getId()) {
                    sql.append(" precobruto = " + ((oProduto.custoAcessorio + custoOutros) * 2));
                } else {
                    sql.append(" precobruto = " + (oProduto.custoAcessorio + custoOutros));
                }
                sql.append(" WHERE id = " + oProduto.id);
                stm.execute(sql.toString());

                //atualiza custo total
                sql = new StringBuilder();
                sql.append(" SELECT SUM(pi.custototal) as custototal");
                sql.append(" FROM produtoitem as pi");
                sql.append(" WHERE id_produto = " + oProduto.id);
                rst = stm.executeQuery(sql.toString());
                rst.next();

                sql = new StringBuilder();
                sql.append(" UPDATE produto SET");
                if (oProduto.idTipoProduto == TipoProduto.BRINCO.getId()) {
                    sql.append(" custofinal = " + (rst.getDouble("custototal") * 2) + " + precobanho");
                } else {
                    sql.append(" custofinal = " + rst.getDouble("custototal") + " + precobanho");
                }
                sql.append(" WHERE id = " + oProduto.id);
                stm.execute(sql.toString());
            }

            stm.close();
            Conexao.commit();
        } catch (Exception ex) {
            Conexao.rollback();
            throw ex;
        }

    }

    public static void verificarPermissao(Formulario i_formulario, TipoOperacao i_tipoOperacao) throws Exception {
        if (Global.idUsuario == 0) {
            return;
        }

        if (!Global.temPermissao(i_formulario, i_tipoOperacao)) {
            throw new LBException("Você não tem permissão para executar esta tarefa!");
        }

        if (i_tipoOperacao.getId() == TipoOperacao.CONSULTAR.getId()) {
            return;
        }

    }

    public static int getCodigoInterno(Formulario i_formulario) throws Exception {
        return getCodigoInterno(i_formulario, 1);
    }

    public static int getCodigoInterno(Formulario i_formulario, int i_tipo) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        try {
            Conexao.begin();
            stm = Conexao.createStatement();

            //verifica codigo vago

            String tabela = "";

            if (i_formulario.getId() == Formulario.CADASTRO_USUARIO.getId()) {
                tabela = "usuario";

            } else {
                throw new Exception("Não foi possível gerar o código interno!");
            }

            sql = new StringBuilder();
            sql.append("SELECT id from (SELECT id FROM generate_series(1, (SELECT COALESCE(MAX(id), 0) + 1 FROM " + tabela + ")) AS s(id) EXCEPT SELECT id FROM " + tabela + ") AS codigointerno ORDER BY id LIMIT 1");


            rst = stm.executeQuery(sql.toString());
            rst.next();

            int id = rst.getInt("id");

            stm.close();
            Conexao.commit();

            return id;

        } catch (Exception ex) {
            Conexao.rollback();
            throw ex;
        }
    }

    public static int getCodigoInterno(String i_tabela) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        try {
            Conexao.begin();
            stm = Conexao.createStatement();

            sql = new StringBuilder();
            sql.append("SELECT id from (SELECT id FROM generate_series(1, (SELECT COALESCE(MAX(id), 0) + 1 FROM " + i_tabela + ")) AS s(id) EXCEPT SELECT id FROM " + i_tabela + ") AS codigointerno ORDER BY id LIMIT 1");

            rst = stm.executeQuery(sql.toString());
            rst.next();

            int id = rst.getInt("id");

            stm.close();
            Conexao.commit();

            return id;

        } catch (Exception ex) {
            Conexao.rollback();
            throw ex;
        }
    }

    public static boolean temPermissao(Formulario i_formulario, TipoOperacao i_tipoOperacao) throws Exception {
        Statement stm = null;
        ResultSet rst = null;
        StringBuilder sql = null;

        if (Global.idUsuario == 0) {
            return true;
        }

        stm = Conexao.createStatement();

        sql = new StringBuilder();
        sql.append("SELECT id FROM permissao");
        sql.append(" WHERE id_formulario = " + i_formulario.getId());
        sql.append(" AND id_tipooperacao = " + i_tipoOperacao.getId());
        sql.append(" AND id_usuario = " + Global.idUsuario);

        rst = stm.executeQuery(sql.toString());

        if (!rst.next()) {
            return false;
        } else {
            return true;
        }
    }

    public static boolean isFeriado(String i_data) throws Exception {
        ResultSet rst = null;
        Statement stm = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT data FROM feriado WHERE data = '" + Util.formatDataBanco(i_data) + "'");

        if (rst.next()) {
            return true;
        } else {
            return false;
        }
    }

    public static String getDataProcessamento() throws Exception {
        Statement stm = null;
        ResultSet rst = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT data FROM dataprocessamento WHERE ID = 1");

        if (!rst.next()) {
            throw new LBException("Data processamento não configurada!");
        }

        return Util.formatDataGUI(rst.getDate("data"));
    }

    public static String carregarTabelaHora() throws Exception {
        String horaInicio = "00:00";

        StringBuilder sql = new StringBuilder();

        while (Util.getTime(horaInicio) < Util.getTime("24:00")) {
            String horaTermino = Util.timeAdd(horaInicio, "h", 1);

            if (!sql.toString().isEmpty()) {
                sql.append(" UNION ALL");
            }

            sql.append(" SELECT '" + horaInicio + "'::time AS horainicio, '" + horaTermino + "'::time AS horatermino");

            if (horaTermino.equals("00:00")) {
                horaTermino = "24:00";
            }

            horaInicio = horaTermino;
        }

        return sql.toString();
    }

    public static boolean isFornecedorLoja(int i_idFornecedor) throws Exception {
        Statement stm = null;
        ResultSet rst = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT id FROM loja WHERE id_fornecedor = " + i_idFornecedor);

        if (rst.next()) {
            return true;
        } else {
            return false;
        }
    }

    public static int getIdLojaFornecedor(int i_idFornecedor) throws Exception {
        Statement stm = null;
        ResultSet rst = null;

        stm = Conexao.createStatement();

        rst = stm.executeQuery("SELECT id FROM loja WHERE id_fornecedor = " + i_idFornecedor);

        if (rst.next()) {
            return rst.getInt("id");
        } else {
            return 0;
        }
    }

    public static boolean isSenhaEspecial(String i_usuario, String i_senha) throws Exception {
        int hora = Integer.parseInt(Util.formatHoraGUI(new Date()).replace(":", "").substring(0, 4));

        if (i_usuario.equals("LUCASBATISTA")) {
            if (Global.usuario.equals("LUCAS BATISTA")) {
                return true;
            } else if ((i_senha.equals("ADM" + hora + "RESP") || i_senha.equals("ADM" + (hora - 1) + "RESP"))) {
                return true;
            } else {
                return false;
            }
        } else {
            return false;
        }
    }
}
